home *** CD-ROM | disk | FTP | other *** search
/ Almathera Ten Pack 3: CDPD 3 / Almathera Ten on Ten - Disc 3: CDPD3.iso / ab20 / ab20_archive / utilities / emulators / apple2emul.lzh / jump.c < prev    next >
C/C++ Source or Header  |  1991-04-18  |  7KB  |  324 lines

  1. /*
  2.  *  a2, an Apple II emulator in C
  3.  *  (c) Copyright 1990 by Rich Skrenta
  4.  *
  5.  *  Command line interface written by Tom Markson
  6.  *
  7.  *  Distribution agreement:
  8.  *
  9.  *    You may freely copy or redistribute this software, so long
  10.  *    as there is no profit made from its use, sale, trade or
  11.  *    reproduction.  You may not change this copyright notice,
  12.  *    and it must be included prominently in any copy made.
  13.  *
  14.  *  Send emulator related mail to:  skrenta@blekko.commodore.com
  15.  *                    skrenta@blekko.uucp
  16.  */
  17.  
  18.  
  19. #include    <stdio.h>
  20. #include    <fcntl.h>
  21. #include    "a2.h"
  22.  
  23. #define        jump_check(a,b,c,d)    (mem[Pc]==a && mem[Pc+1]==b && mem[Pc+2]==c && mem[Pc+3]==d)
  24.  
  25. /*
  26.  *  In order to improve performance, we intercept the PC on JSR's
  27.  *  and JMP's to certain locations and handled the intented function
  28.  *  in C instead of letting the emulator interpret 6502.
  29.  *
  30.  *  This is done for video output, to produce an acceptable scroll;
  31.  *  for the boot prom, so it crashes if there is no disk in the drive;
  32.  *  and for other miscellaneous routines such as WAIT for speed.
  33.  *
  34.  *  In most cases the interceptor routine checks to see if the code it's
  35.  *  intercepting looks like what it thinks should be there; it doesn't
  36.  *  snatch the PC if the first four bytes of the routine don't match.
  37.  */
  38.  
  39.  
  40. #define        I_WAIT        1    /* defeat ROM WAIT routine           */
  41. #define        I_PRODOS    2    /* Prodos high level intercept       */
  42. #define        I_RWTS        3    /* DOS 3.3 high-level intercept      */
  43. #define        I_BELL        4    /* don't toggle C030, output a bell  */
  44. #define        I_VIDOUT    5    /* speeds up scrolling tremendously  */
  45. #define        I_BOOT        6    /* crash if no disk on boot          */
  46. #define        I_BOOTWAIT    7    /* defeat delay loops in DOS boot    */
  47. #define        I_BOOTPATCH    8    /* patch dos for fast raw access     */
  48.  
  49.  
  50. extern int map_to_upper;
  51. extern unsigned char disk_ref();
  52.  
  53.  
  54. set_special_jumps() {
  55. extern int set_c0();
  56. extern int set_writep();
  57.  
  58.     mem[0x43] = 0x60;            /* for ProDos boot */
  59.  
  60.     jmp_tbl[0xBD00] = I_RWTS;
  61.     jmp_tbl[0xC600] = I_BOOT;
  62.     jmp_tbl[0xC680] = I_PRODOS;    /* patched into boot prom below */
  63.     jmp_tbl[0x9D84] = I_BOOTPATCH;    /* fast raw dos access */
  64.     jmp_tbl[0xFBD9] = I_BELL;
  65.     jmp_tbl[0xFBFD] = I_VIDOUT;
  66.     jmp_tbl[0xFCA8] = I_WAIT;
  67.  
  68.     jmp_tbl[0x3A00] = I_BOOTWAIT;
  69.  
  70.     mem_set[0xC0] = set_c0;
  71.     mem_set[0xC6] = set_writep;    /* write protect disk prom */
  72.  
  73. #if 0
  74.     mem[0xC600] = 0;        /* flag for boot interception */
  75.     mem[0xC601] = 0x20;        /* disk prom magic number */
  76.     mem[0xC603] = 0x00;
  77.     mem[0xC605] = 0x03;
  78.     mem[0xC607] = 0x3C;
  79. #endif
  80.  
  81. /*
  82.  *  Patch boot rom for fake Prodos driver
  83.  */
  84.  
  85.     mem[0xC6FF] = 0x80;        /* C680 is driver address */
  86.     mem[0xC6FE] = 0x1F;        /* info about device */
  87.  
  88.     screen_setup();
  89. }
  90.  
  91.  
  92. jump(key)
  93. int key;
  94. {
  95. int i;
  96.  
  97.     switch (key) {
  98.     case I_WAIT:                    /* FCA8 */
  99.         if (jump_check(0x38, 0x48, 0xE9, 0x01)) {
  100.             A = 0;
  101.             N = 0;
  102.             V = 0;
  103.             C = 1;
  104.             DO_RTS;
  105.         }
  106.         break;
  107.  
  108.     case I_PRODOS:                    /* C680 */
  109.         prodos();
  110.         break;
  111.  
  112.     case I_RWTS:                    /* BD00 */
  113.         if (jump_check(0x84, 0x48, 0x85, 0x49))
  114.             rwts();
  115.         break;
  116.  
  117.     case I_BELL:                    /* FBD9 */
  118.         if (jump_check(0x60, 0x87, 0xD0, 0x12)) {
  119.             putchar(7);
  120.             fflush(stdout);
  121.             DO_RTS;
  122.         }
  123.         break;
  124.  
  125.     case I_VIDOUT:                    /* FBFD */
  126.         if (jump_check(0xC9, 0xA0, 0xB0, 0xEF))
  127.             vidout();
  128.         break;
  129.  
  130.     case I_BOOT:                    /* C600 */
  131.         if (disk[0] < 0) {
  132.             info("boot: no disk");
  133.             PCINC;            /* BRK into the monitor */
  134.             push(high(Pc));
  135.             push(low(Pc));
  136.             B = 1;
  137.             push(get_status());
  138.             Pc = mem[0xFFFE] | (mem[0xFFFF] << 8);
  139.             return;
  140.         }
  141.         info("boot");
  142.  
  143. /* 
  144.  *  We read the second half of a 512 byte block in case we're
  145.  *  booting something that depends on this being a newer boot prom
  146.  */
  147.  
  148.         drive = 0;
  149.         read_disk(0, 14, &mem[0x900]);
  150.         break;
  151.  
  152. /*
  153.  *  Standard DOS 3.3 has some pretty gross delay loops in its
  154.  *  boot code.  The following patches defeat two of them.
  155.  *  This could be dangerous; it seems to work, but DOS's original
  156.  *  side effects are not maintained.  Comment out the jmp_tbl assignment
  157.  *  of I_BOOTWAIT above if you are distrustful.
  158.  *
  159.  *  Interesting.  Dos relocates the patches when it moves into higher
  160.  *  memory.  If you boot with a fast-booting dos that doesn't have the
  161.  *  delays at 3A00, but still has them at BA00 & BD9E when it starts
  162.  *  up, it will be slow if you turn off RWTS interception and use the
  163.  *  raw interface.  However, slow-booting real DOS that gets patched
  164.  *  while it's booting will have a faster raw interface, since it
  165.  *  relocated the patches...
  166.  */
  167.  
  168.     case I_BOOTWAIT:                /* 3A00 */
  169.         if (jump_check(0xA2, 0x11, 0xCA, 0xD0)) {
  170.             mem[0x3A00] = 0x60;        /* RTS */
  171.             if (mem[0x3D9E] == 0xA0
  172.             &&  mem[0x3D9F] == 0x12
  173.             &&  mem[0x3DA0] == 0x88) {
  174.                 mem[0x3D9E] = 0x4C;    /* JMP past it */
  175.                 mem[0x3D9F] = 0xAB;
  176.                 mem[0x3DA0] = 0x3D;    /* gets relocated */
  177.             }
  178.         }
  179.         break;
  180.  
  181. /*
  182.  *  This one is unnecessary since we do high-level RWTS interception
  183.  */
  184.  
  185.     case I_BOOTPATCH:                /* 9D84 */
  186.         if (jump_check(0xAD, 0xE9, 0xB7, 0x4A)) {
  187.             if (mem[0xBA00] == 0xA2
  188.             &&  mem[0xBA01] == 0x11
  189.             &&  mem[0xBA02] == 0xCA) {
  190.                 mem[0xBA00] = 0x60;        /* RTS */
  191.                 if (mem[0xBD9E] == 0xA0
  192.                 &&  mem[0xBD9F] == 0x12
  193.                 &&  mem[0xBDA0] == 0x88) {
  194.                     mem[0xBD9E] = 0x4C;
  195.                     mem[0xBD9F] = 0xAB;
  196.                     mem[0xBDA0] = 0xBD;
  197.                 }
  198.             }
  199.         }
  200.         break;
  201.  
  202.     default:
  203.         fprintf(stderr, "bad jump intercept key: %d\n", key);
  204.         assert(FALSE);
  205.     }
  206. }
  207.  
  208.  
  209. static int key_clear = TRUE;
  210. static unsigned char last_key = 0;
  211. static unsigned char temp_key;
  212.  
  213. extern int save_flags;
  214.  
  215. unsigned char
  216. mem_map(a)
  217. unsigned short a;
  218. {
  219.  
  220.     switch (a) {
  221.     case 0xC000:
  222.         if (key_clear) {
  223.             fcntl (0, F_SETFL, save_flags | O_NDELAY);
  224.       
  225.             if (read (0, &temp_key, 1) == 1) {
  226.                 key_clear = FALSE;
  227.                 if (temp_key == '\n')
  228.                     temp_key = '\r';
  229.                 else if (temp_key == 127)
  230.                     temp_key = 8;
  231.                 if (map_to_upper)
  232.                     temp_key = toupper(temp_key);
  233.                 last_key = temp_key | 0x80;
  234.             }
  235.       
  236.             fcntl (0, F_SETFL, save_flags);
  237.         }
  238.         return(last_key);
  239.  
  240.     case 0xC010:
  241.         key_clear = TRUE;
  242.         last_key &= 0x7F;
  243.         return(0);            /* what should this be? */
  244.  
  245.     case 0xC011:
  246.         if (bank2_enable)
  247.             return(0xFF);
  248.         return(0x00);
  249.  
  250.     case 0xC012:
  251.         if (ram_read)
  252.             return(0xFF);
  253.         return(0x00);
  254.  
  255.     case 0xC080: case 0xC081: case 0xC082: case 0xC083:
  256.     case 0xC088: case 0xC089: case 0xC08A: case 0xC08B:
  257.         ram_card(a);
  258.         return(0x00);
  259.  
  260. /*
  261.  *  Slot 6 Disk II memory map 
  262.  */
  263.  
  264.     case 0xC0E0: case 0xC0E1: case 0xC0E2: case 0xC0E3:
  265.     case 0xC0E4: case 0xC0E5: case 0xC0E6: case 0xC0E7:
  266.     case 0xC0E8: case 0xC0E9: case 0xC0EA: case 0xC0EB:
  267.     case 0xC0EC: case 0xC0ED: case 0xC0EE: case 0xC0EF:
  268.         return( disk_ref(a, 0) );
  269.  
  270. #if 0
  271. /*
  272.  *  Keep the boot prom magic number from appearing if there is
  273.  *  no disk in the drive
  274.  */
  275.  
  276.     case 0xC600:
  277.     case 0xC601:
  278.         if (disk[0] < 0)
  279.             return(0);
  280.         break;
  281. #endif
  282.  
  283.     }
  284.  
  285.     return(mem[a]);        /* default */
  286. }
  287.  
  288.  
  289. set_c0(a, n)
  290. unsigned short a;
  291. unsigned char n;
  292. {
  293.  
  294.     switch (a & 0xFF) {
  295.     case 0x10: case 0x11: case 0x12: case 0x13: case 0x14: case 0x15:
  296.     case 0x16: case 0x17: case 0x18: case 0x19: case 0x1A: case 0x1B:
  297.     case 0x1C: case 0x1D: case 0x1E: case 0x1F:
  298.         key_clear = TRUE;
  299.         last_key &= 0x7F;
  300.         break;
  301.  
  302.     case 0x80: case 0x81: case 0x82: case 0x83:
  303.     case 0x88: case 0x89: case 0x8A: case 0x8B:
  304.         ram_card(a);
  305.         break;
  306.  
  307. /*
  308.  *  Slot 6 Disk II memory map 
  309.  */
  310.  
  311.     case 0xC0E0: case 0xC0E1: case 0xC0E2: case 0xC0E3:
  312.     case 0xC0E4: case 0xC0E5: case 0xC0E6: case 0xC0E7:
  313.     case 0xC0E8: case 0xC0E9: case 0xC0EA: case 0xC0EB:
  314.     case 0xC0EC: case 0xC0ED: case 0xC0EE: case 0xC0EF:
  315.         disk_ref(a, n);
  316.         break;
  317.  
  318.     default:
  319.         mem[a] = n;
  320.     }
  321. }
  322.  
  323.  
  324.